package com.googlecode.loframework.view
{
	import com.googlecode.loframework.core.NotificationNames;
	import com.googlecode.loframework.model.ProjectDataProxy;
	import com.googlecode.loframework.view.components.quizzes.IQuiz;
	
	import flash.events.Event;
	
	import mx.core.UIComponent;
	
	import org.puremvc.as3.interfaces.INotification;
	import org.puremvc.as3.patterns.mediator.Mediator;
	
	/**
	 * Links the PageHolder component to the PureMVC framework. Determines the loading
	 * and unloading of pages. Each time a page is loaded, any associated component mediators are added. 
	 * @author ~martin
	 * 
	 */
	public class PageHolderMediator extends Mediator
	{
		/**
		 * Identifier 
		 */
		public static const NAME:String = "PageHolderMediator";
		
		/**
		 * Constructor 
		 * @param viewComponent
		 * 
		 */
		public function PageHolderMediator(viewComponent:IComponent)
		{
			super(NAME, viewComponent);
		}
		
		/**
		 * Triggered by PureMVC. 
		 * 
		 */
		override public function onRegister():void
		{
			// if there are any pages present at this stage, the first one is loaded into PageLoader
			if(viewRef.numPages > 0)
			{			
				// pages are scanned for components that may require further processing
				// once sent they have their isLoaded property set to true. This
				// means they can be handled as loaded pages subsequently				
				processPageList();
				
				viewRef.changePage(0);
			} 

			// we may not capture all pages added however. We need to listen for 
			// pages that might be added after the mediator has been registered
			viewRef.addEventListener(PageHolder.PAGE_ADDED, onPageAdded);
						
		}
		
		/**
		 * Lists notification of interest in page index changes. 
		 * @return 
		 * 
		 */
		override public function listNotificationInterests():Array
		{
			var list:Array = super.listNotificationInterests();
			
			list.push(ProjectDataProxy.PAGE_INDEX_CHANGED);
			
			return list;
		}
		
		/**
		 * Handles notifications. 
		 * @param notification
		 * 
		 */
		override public function handleNotification(notification:INotification):void
		{
			
			switch(notification.getName())
			{
				case ProjectDataProxy.PAGE_INDEX_CHANGED:

					viewRef.changePage(notification.getBody() as int);
					searchTree(viewRef.loadedPage as UIComponent);

					break;
			}
		}
		
		/**
		 * Recursive function used to search the display lists of a UIComponent and all its children. 
		 * Calls the addMediator function when it finds a component.
		 * @param child
		 * 
		 */
		protected function searchTree(child:UIComponent, startup:Boolean = false):void
		{
			for(var i:uint=0; i<child.numChildren; i++)
			{
				if(child.getChildAt(i) as UIComponent != null)
				{	
					if(child.getChildAt(i) is IComponent)
					{
						// the pages have an isLoaded property. This is only set to false once.
						// It enables any components to be set up properly
						// before use. For example, some require a proxy to store data
						if(startup == true)
						{	
							componentAdded(child.getChildAt(i) as IComponent);
						}else
						{
							// we need to register any mediators required for the view components. This 
							// happens, for example, when a page is changed
							allocateMediator(child.getChildAt(i) as IComponent);
						}				
					}
					
					// recurively dig for all children of the original child
					searchTree((child.getChildAt(i) as UIComponent), startup);	
				}
			}
		}
		
		/**
		 * Notifies the PureMVC framework that a component has been discovered that
		 * requires further action to set up.
		 *  
		 * @param component
		 * 
		 */
		protected function componentAdded(component:IComponent):void
		{	
			// use commands
			if(component is IQuiz)
			{
				sendNotification(NotificationNames.COMPONENT_QUIZ_ITEM_ADDED, component);
			}		
		}
		
		/**
		 * Associates a component with its mediator. 
		 * @param component
		 * 
		 */
		protected function allocateMediator(component:IComponent):void
		{	
			
			// use commands to add mediators
			if(component is IQuiz)
			{
				sendNotification(NotificationNames.COMPONENT_QUIZ_ITEM_REGISTER_MEDIATOR, component);
			}		
		}
		
		/**
		 * Triggered when a page is added to PageHolder dynamically, after creation is complete. 
		 * @param evt
		 * 
		 */
		protected function onPageAdded(evt:Event):void
		{
			processPageList();

			if(viewRef.numPages == 1)
			{
				viewRef.changePage(0);
			} 	
				
			
		}
		
		/**
		 * Works through all the pages in the pageList Array and processes them. 
		 * 
		 */
		protected function processPageList():void
		{
			for(var i:uint=0; i<viewRef.pageList.length; i++)
			{
				(viewRef.pageList[i] as IPage).isLoaded = true;
				searchTree(viewRef.pageList[i] as UIComponent, true);
			}
			
			sendNotification(NotificationNames.NUM_PAGES, viewRef.numPages);
			sendNotification(NotificationNames.PAGES_LOADED, viewRef.pageList);
		}
		
		/**
		 * Returns a typed reference to the view component.
		 * @return 
		 * 
		 */
		protected function get viewRef():PageHolder
		{
			return viewComponent as PageHolder;
		}
	}
}